ASM-16bit Zufallszahlen ohne Wiederholung

← Zurück zum Forum

MADS

ct, count, copyfrom, test sind alles zeropage words t_rand ist die Tabelle, wo die 16bit Werte abgelegt werden (also ist sie am Ende exakt doppelt so groß, we man Zahlen haben möchte.

    .zpvar  .word   count,copyfrom,ct,test

    .proc gen_zufall    ;800 16bit Zufallszahlen ohne Wiederholung erstellen
    mwa #0 count
    .local gen_rand16
    lda random
    sta copyfrom
@   lda random
    and #$f
    cmp #4
    bcs @-
    sta copyfrom+1
    cpw copyfrom #800   ;gewünschte maximale Zahl
    bcs gen_rand16
;--- Test ob schon eingeschrieben in unserer Tabelle
    mwa #0 ct
    mwa #t_rand test
lp  ldy #1
    lda copyfrom+1
    cmp (test),y
    bcc next    ;kleiner
    bne next    ;größer
    dey
    lda copyfrom
    cmp (test),y
    beq gen_rand16  ;gleich -> neue Zahl erstellen
next    inw ct
    adw test #2
    cpw count ct
    bcs lp
;---
set lda copyfrom
chg sta t_rand
    lda copyfrom+1
chg1    sta t_rand+1
    inw count
    adw chg+1 #2
    adw chg1+1 #2
    cpw count #799  ;gewünschte Anzahl-1
    jcc gen_rand16
    .endl
    rts
    .endp
;---
t_rand
    .ds 1600

Warnung! Die Routine funktioniert, aber ES DAUERT. Ich nutze daher für mein Projekt eine am PC erstellte Liste, die dann halt nicht so ganz zufällig ist, für den Zweck ausreicht und halt sofort geht. Ich benötigte exakt 800 Zahlen, zufällig und alle von 0 bis 799. Wenn Ihr nur einfach Zufallszahlen benötigt, die sich nicht wiederholen, kann das:

    and #$f
    cmp #4
    bcs @-

und auch das:

    cpw copyfrom #800   ;gewünschte maximale Zahl
    bcs gen_rand16

weggelassen werden. Wo doppelte Zahlen kein Problem sind, einfach alles zwischen den beiden ";---" weglassen. Dann ist das auch echt schnell.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Für meinen speziellen Fall habe ich einen falschen Ansatz gehabt. Ich will ja exakt 800 Zahlen von 0 bis 799 zufällig haben. Da kann ich ja einfach eine sortierte Tabelle von 0 bis 799 zufällig x mal durchtauschen und es sollte dann auch nicht mehr so lange dauern...

Im Listing oben muss man ja ewig suchen, ob die Zahl schon vorhanden ist. Manchmal ist der erste Ansatz nicht immer der Beste 🤣

Wenn man natürlich z. B. eine Liste mit 100 Zahlen haben möchte, im Bereich von 0 bis 799 ohne Dopplung, ist obige Routine wohl die Wahl. Dort sind dann ja nicht alle 800 möglichen Zahlen drin.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

So, hier der Code zu der oben skizzierten Idee. Es ist wirklich "geringfügig" schneller 😂

    .zpvar  .word   copyfrom,copyto,ct,test,test2

    .local gen_table
    mwa #0 ct
    mwa #t_rand test
lp  ldy #0
    lda ct
    sta (test),y
    iny
    lda ct+1
    sta (test),y
    inw ct
:2  inw test
    cpw ct #800
    bne lp
    .endl
;---
    .local shuffle
    mwa #0 ct
start
;--- generate 2 numbers to change
gen_rand16_1
    lda random
    sta test
@   lda random
    and #$f
    cmp #4
    bcs @-
    sta test+1
    cpw test #800
    bcs gen_rand16_1
gen_rand16_2
    lda random
    sta test2
@   lda random
    and #$f
    cmp #4
    bcs @-
    sta test2+1
    cpw test2 #800
    bcs gen_rand16_2
    cpw test test2
    beq gen_rand16_2
;--- multiply by 2 as table is a word table
    clc
    rol test
    rol test+1
    clc
    rol test2
    rol test2+1
;--- change
    adw test #t_rand copyfrom
    adw test2 #t_rand copyto
    ldy #0
lo  mva (copyfrom),y test
    mva (copyto),y (copyfrom),y
    mva test (copyto),y
    iny
hi  mva (copyfrom),y test
    mva (copyto),y (copyfrom),y
    mva test (copyto),y
    inw ct
    cpw ct #800 ;wir würfeln jetzt einfach auch 800 mal das Feld durch
    jne start
    .endl

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat